package com.isoft.c2team3service2.filter;

import com.isoft.c2team3service2.entity.UserDTO;
import com.isoft.c2team3service2.util.JwtUtil;
import com.isoft.c2team3service2.util.UserHolder;
import io.jsonwebtoken.Claims;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.isoft.c2team3service2.util.RedisConstants.USER_LOGIN_KEY;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtil;
    private final StringRedisTemplate stringRedisTemplate;

    public JwtAuthenticationFilter(JwtUtil jwtUtil, StringRedisTemplate stringRedisTemplate) {
        this.jwtUtil = jwtUtil;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authHeader = request.getHeader("Authorization");
        String token = null;

        // 提取并清理Token（去除Bearer前缀）
        if (StringUtils.hasText(authHeader) && authHeader.startsWith("Bearer ")) {
            token = authHeader.substring(7).trim();
            System.out.println("清理后的Token: " + token);
        }

        if (StringUtils.hasText(token)) {
            try {
                // 解析JWT获取基本信息
                Claims claims = jwtUtil.parseToken(token);
                Integer id = claims.get("userId", Integer.class);
                String username = claims.get("username", String.class);
                List<String> roles = (List<String>) claims.get("roles");

                // 生成与登录时一致的Redis键
//                String hashKey = DigestUtils.md5DigestAsHex(token.getBytes());
                String redisKey = USER_LOGIN_KEY + token;
                System.out.println("查询Redis的键: " + redisKey);

                // 从Redis获取完整用户信息
                Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(redisKey);
                if (userMap.isEmpty()) {
                    System.out.println("Redis中未找到该Token对应的用户信息");
                    // 若Redis无用户信息，尝试从JWT自身获取基础信息构建UserDTO（降级处理）
                    UserDTO userDTO = new UserDTO();
                    userDTO.setId(id);
                    userDTO.setUsername(username);
                    userDTO.setRoles(roles);
                    UserHolder.saveUser(userDTO);
                } else {
                    // 从Redis map中创建UserDTO
                    UserDTO userDTO = createUserDTOFromRedisMap(userMap, id, username, roles);

                    // 保存到UserHolder并打印日志验证
                    UserHolder.saveUser(userDTO);
                    System.out.println("UserHolder保存的用户信息，id: " + userDTO.getId() + "，username: " + userDTO.getUsername() + "，artistId: " + userDTO.getArtistId());

                    // 设置权限信息
                    List<SimpleGrantedAuthority> authorities = new ArrayList<>();
                    if (roles != null && !roles.isEmpty()) {
                        authorities = roles.stream()
                                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                                .collect(Collectors.toList());
                    }
                    UsernamePasswordAuthenticationToken authentication =
                            new UsernamePasswordAuthenticationToken(username, null, authorities);
                    SecurityContextHolder.getContext().setAuthentication(authentication);

                    // 刷新过期时间（使用正确的redisKey）
                    stringRedisTemplate.expire(redisKey, 60, TimeUnit.MINUTES);
                }
            } catch (Exception e) {
                System.err.println("Token解析或Redis校验失败：" + e.getMessage());
                e.printStackTrace();
                SecurityContextHolder.clearContext();
                UserHolder.removeUser();
                // 可在此处添加响应头，告知前端Token失效等信息
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"code\":401,\"message\":\"Token无效或已过期，请重新登录\"}");
                return;
            }
        }

        filterChain.doFilter(request, response);
    }

    /**
     * 从Redis Map中创建完整的UserDTO对象
     */
    private UserDTO createUserDTOFromRedisMap(Map<Object, Object> userMap, Integer userId, String username, List<String> roles) {
        UserDTO userDTO = new UserDTO();
        userDTO.setId(userId);
        userDTO.setUsername(username);
        userDTO.setRoles(roles);

        // 解析 artistId
        Object artistIdObj = userMap.get("artistId");
        if (artistIdObj != null) {
            try {
                String artistIdStr = artistIdObj.toString().trim();
                if (!artistIdStr.isEmpty()) {
                    userDTO.setArtistId(Integer.parseInt(artistIdStr));
                    System.out.println("从Redis成功提取artistId: " + userDTO.getArtistId());
                } else {
                    System.out.println("Redis中artistId字段为空字符串，设为null");
                    userDTO.setArtistId(null);
                }
            } catch (NumberFormatException e) {
                System.out.println("artistId格式错误，值为: " + artistIdObj + "，错误信息: " + e.getMessage());
                userDTO.setArtistId(null);
            }
        } else {
            System.out.println("Redis中未找到artistId字段，设为null");
            userDTO.setArtistId(null);
        }

        // 解析 nickName
        if (userMap.get("nickName") != null) {
            userDTO.setNickName(userMap.get("nickName").toString());
        }

        // 解析 userType
        if (userMap.get("userType") != null) {
            try {
                userDTO.setUserType(Integer.parseInt(userMap.get("userType").toString()));
            } catch (NumberFormatException e) {
                System.out.println("userType格式错误: " + userMap.get("userType"));
            }
        }

        // 解析 isArtist
        if (userMap.get("isArtist") != null) {
            userDTO.setIsArtist(userMap.get("isArtist").toString());
        }

        return userDTO;
    }
}